package de.rts.xml;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.Node;

import de.rts.components.RailComponent;
import de.rts.components.SensorType;

public class Validator
{
  private static final String[]     attribs           = RailComponent.XML_TAGS.get("attributes");
  private static final String       ROOT_TAG          = RailComponent.XML_TAGS.get("root")[0];
  private static final List<String> FIRST_LEVEL_TAGS  = Arrays.asList(RailComponent.XML_TAGS.get("firstLevel"));
  private static final List<String> SECOND_LEVEL_TAGS = Arrays.asList(RailComponent.XML_TAGS.get("secondLevel"));
  private static final List<String> THIRD_LEVEL_TAGS  = Arrays.asList(RailComponent.XML_TAGS.get("thirdLevel"));

  private static void validateRoot(Element root) throws ParseException
  {
    if (!root.getName().equals(ROOT_TAG))
      throw new ParseException("Invalid XML. Expected '" + ROOT_TAG + "' as root.");
  }

  private static void validateFirstLevelTag(Element tag) throws ParseException
  {
    String param = tag.getName();
    if (!FIRST_LEVEL_TAGS.contains(param))
      throw new ParseException("Invalid XML. The tag '" + param + "' is not a first level tag.");
  }

  private static void validateSecondLevelTag(Element tag) throws ParseException
  {
    String param = tag.getName();
    if (!SECOND_LEVEL_TAGS.contains(param))
      throw new ParseException("Invalid XML. The tag '" + param + "' is not a second level tag.");
  }

  private static void validateThirdLevelTag(Element tag) throws ParseException
  {
    String param = tag.getName();
    if (!THIRD_LEVEL_TAGS.contains(param))
      throw new ParseException("Invalid XML. The tag '" + param + "' is not a third level tag.");
  }

  @SuppressWarnings("unchecked")
  public static void validateXML(Element root) throws ParseException
  {
    validateRoot(root);
    for (Iterator<Element> rootIter = (Iterator<Element>) root.elementIterator(); rootIter.hasNext();)
    {
      Element firstLevelElem = (Element) rootIter.next();
      if (firstLevelElem != null) validateFirstLevelTag(firstLevelElem);
      for (Iterator<Element> firstIter = firstLevelElem.elementIterator(); firstIter.hasNext();)
      {
        Element secondLevelElem = (Element) firstIter.next();
        if (secondLevelElem != null) validateSecondLevelTag(secondLevelElem);
        for (Iterator<Element> secondIter = secondLevelElem.elementIterator(); secondIter.hasNext();)
        {
          Element thirdLevelElem = (Element) secondIter.next();
          if (thirdLevelElem != null) validateThirdLevelTag(thirdLevelElem);
        }
      }
    }
  }

  @SuppressWarnings("unchecked")
  public static List<Attribute> validateNodeAttributes(Node n) throws ParseException
  {
    Element e = (Element) n;
    List<Attribute> list = e.attributes();
    for (Attribute attribute : list)
    {
      String aname = attribute.getName();
      if (!Arrays.asList(attribs).contains(aname))
        throw new ParseException("Invalid XML. Expected attribute '" + aname + "' is missing.");
    }
    return list;
  }

  public static Attribute validateIdentifictorAttributes(Node n) throws ParseException
  {
    Element e = (Element) n;
    Attribute id = (Attribute) e.attributes().get(0);
    String aname = id.getName();
    if (!"id".equals(aname)) throw new ParseException("Invalid XML. The attribute '" + aname + "' is not allowed.");
    return id;
  }

  public static SensorType validateSensorType(String type) throws ParseException
  {
    List<SensorType> sensorTypeList = Arrays.asList(SensorType.values());
    SensorType sensorType = SensorType.valueOf(type);
    if (!sensorTypeList.contains(sensorType))
      throw new ParseException("Invalid XML. The sensor type '" + type + "' is not valid.");
    return sensorType;
  }

}
